﻿#include "HP_Buffer.h"
#include "lua.hpp"

HP_Buffer::HP_Buffer(int flag, int len, int max_seq)
{
	m_flag = flag;
	m_buflen = len;
	m_bodylen = len - sizeof(HP_Header);
	m_data = new unsigned char[len];
	memset(m_data, 0, len);
	m_head = (HP_Header*)m_data;
	m_wint = (int*)(m_data + sizeof(HP_Header));
	m_rint = (int*)m_data;
	m_code = NULL;

	m_maxseq = max_seq;
	m_seq = 0;
}

HP_Buffer::~HP_Buffer(void)
{
	delete m_data;
}

void HP_Buffer::Reset() {
	m_i = 0;
	m_len = sizeof(HP_Header);
	m_lock = false;
	memset(m_data, 0, m_buflen);
}

bool HP_Buffer::AddNumber(int v) {
	if (m_len + sizeof(int) < m_bodylen && !m_lock)
	{
		m_wint[m_i++] = v;
		m_len += sizeof(int);
		return true;
	}
	return false;
}

bool HP_Buffer::AddString(const char* v, int len) {
	if (m_len + len < m_bodylen && !m_lock)
	{
		memcpy(m_data + m_len, v, len);
		m_len += len;
		m_lock = true;
		return true;
	}
	return false;
}

void HP_Buffer::Finish() {
	m_head->flag = m_flag;
	m_head->seq = m_seq;
	m_head->len = m_len - this->GetHeaderLen();
	m_head->qty = m_i;
	m_seq++;
	m_lock = true;
	if (m_code)
	{
		unsigned char* data = m_data + this->GetHeaderLen();
		int k = 0;
		for (int i = 0; i < m_head->len; i++)
		{
			data[i] ^= m_code[k++];
			if (k >= m_codelen)
			{
				k = 0;
			}
		}
	}

	if (m_seq > m_maxseq)
	{
		m_seq = 1;
	}
}

unsigned int HP_Buffer::GetHeaderLen() {
	return sizeof(HP_Header) - 4;	//第四位是整数个数
}

unsigned int HP_Buffer::CheckHeader() {
	if (m_head->flag == m_flag)
	{
		m_len = m_head->len;
		return m_len;
	}
	return 0;
}

unsigned char* HP_Buffer::GetPtr() {
	return m_data;
}

unsigned int HP_Buffer::GetLen() {
	return m_len;
}

void HP_Buffer::SetCode(int* psd, int len)
{
	if (m_code)
	{
		delete[]m_code;
		m_code = NULL;
	}
	m_code = new int[len];

	memset(m_code, 0, sizeof(int) * len);
	memcpy(m_code, psd, sizeof(int) * len);
	m_codelen = len;
}

void HP_Buffer::SetComp(bool v) {
	m_comp = v;
}

static int Reset(lua_State* L)
{
	HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
	ud->Reset();
	return 0;
}

static int AddNumber(lua_State* L)
{
	HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
	ud->AddNumber(luaL_checkinteger(L, 2));
	return 0;
}

static int AddString(lua_State* L)
{
	HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
	size_t len = 0;
	const char* v = luaL_checklstring(L, 2, &len);

	char* buff = (char*)malloc(len + 1);
	memset(buff, 0, len + 1);
	memcpy(buff, v, len);
	//const char* v = luaL_checkstring(L, 2);
	ud->AddString(v, len);
	return 0;
}

static int Finish(lua_State* L)
{
	HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
	ud->Finish();
	return 0;
}

static int GetHeaderLen(lua_State* L)
{
	HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
	int ret = ud->GetHeaderLen();
	lua_pushinteger(L, ret);
	return 1;
}

static int CheckHeader(lua_State* L)
{
	HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
	int ret = ud->CheckHeader();
	lua_pushinteger(L, ret);
	return 1;
}

static int SetCode(lua_State* L)
{
	HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
	size_t len = 0;
	if (!lua_istable(L, 2))
	{
		luaL_error(L, "passwd isn't a table");
		return 0;
	}

	int pwd[1024] = { 0 };
	int codelen = 0;

	/*  表放在索引 't' 处 */
	lua_pushnil(L);  /* 第一个键 */
	while (lua_next(L, 2) != 0) {
		int index = luaL_checkinteger(L, -2);
		int value = luaL_checkinteger(L, -1);
		pwd[index - 1] = value;
		codelen++;
		lua_pop(L, 1);
	}

	ud->SetCode(pwd, codelen);

	return 0;
}

static int GetData(lua_State* L)
{
	HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");

	//数据解密
	if (ud->m_code)
	{
		unsigned char* data = ud->m_data;
		int k = 0;
		for (int i = 0; i < ud->m_len; i++)
		{
			data[i] ^= ud->m_code[k++];
			if (k >= ud->m_codelen)
			{
				k = 0;
			}
		}
	}

	lua_newtable(L);//创建一个表格，放在栈顶

	ud->m_qty = ud->m_rint[0];

	int stroff = (ud->m_qty + 1) * sizeof(int);
	if (stroff < ud->m_bodylen)
	{
		for (int i = 0; i < ud->m_qty; i++)
		{
			lua_pushinteger(L, ud->m_rint[i + 1]);
			lua_seti(L, -2, i + 1);
		}

		if (ud->m_len - stroff > 0)
		{
			//lua_pushlstring(L, (const char*)ud->m_data + stroff, ud->m_len - stroff);
			lua_pushstring(L, (const char*)ud->m_data + stroff);
			lua_seti(L, -2, ud->m_qty + 1);
		}
	}

	return 1;
}

static int Creat_HP_Buffer(lua_State* L) {
	int flag = luaL_checkinteger(L, 1);
	int len = luaL_checkinteger(L, 2);
	int maxseq = luaL_checkinteger(L, 3);
	HP_Buffer* p = new HP_Buffer(flag, len, maxseq);
	HP_Buffer** ud = (HP_Buffer**)lua_newuserdata(L, sizeof(HP_Buffer*));
	*ud = p;
	luaL_setmetatable(L, "HP_Buffer");
	return 1;
}

static int Destroy_HP_Buffer(lua_State* L) {
	HP_Buffer* ud = *(HP_Buffer**)luaL_checkudata(L, 1, "HP_Buffer");
	delete ud;
	return 0;
}


#ifdef _WIN32
extern "C"
#endif // _WIN32
LUALIB_API
int luaopen_ghpsocket_buffer(lua_State * L)
{
	luaL_Reg methods[] = {
		{"Reset",Reset},
		{"AddNumber",AddNumber},
		{"AddString",AddString},
		{"Finish",Finish},
		{"GetHeaderLen",GetHeaderLen},
		{"CheckHeader",CheckHeader},
		{"SetCode",SetCode},
		{"GetData",GetData},
		{NULL, NULL},
	};
	setvbuf(stdout, NULL, _IONBF, 0);
	luaL_newmetatable(L, "HP_Buffer");
	luaL_newlib(L, methods);
	lua_setfield(L, -2, "__index");
	lua_pushcfunction(L, Destroy_HP_Buffer);
	lua_setfield(L, -2, "__gc");
	lua_pop(L, 1);

	lua_pushcfunction(L, Creat_HP_Buffer);
	return 1;
}
